﻿using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace CountTools
{
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    public class CodeNumber : IExternalCommand
    {
        private string path;

        public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elements)
        {
            UIDocument uidoc = cmdData.Application.ActiveUIDocument;
            Document doc = uidoc.Document;

            this.path = doc.PathName;
            int lastChar = path.LastIndexOf(@"\");
            path = path.Remove(lastChar + 1);
            path += doc.Title.Substring(0, doc.Title.Length - 4) + "算量信息.xml";
            XmlDocument xml = new XmlDocument();
            xml.Load(path);

            List<string> elementTypes = new List<string>();
            Dictionary<string, List<string>> elementsList = new Dictionary<string, List<string>>();
            XmlNode mainNode = xml.SelectSingleNode("算量信息");
            var nodes = mainNode.ChildNodes;
            foreach (XmlNode childNode in nodes)
            {
                string elementId = childNode.Name;
                XmlNode name = childNode.SelectSingleNode("项目名称");
                string codeName = name.InnerText;

                if (elementsList.ContainsKey(codeName))
                {
                    elementsList[codeName].Add(elementId);
                }
                else
                {
                    elementsList.Add(codeName, new List<string>());
                    elementsList[codeName].Add(elementId);
                    elementTypes.Add(codeName);
                }
            }


            XmlDocument xmlRebar = new XmlDocument();
            string newPath = path.Replace("清单规则", "算量信息");
            //if (File.Exists(newPath))
            //{
            //    elementTypes.Add("010515001 现浇构件钢筋");
            //}

            elementTypes.Sort();

            CodeNumberRuleForm ruleForm = new CodeNumberRuleForm(elementTypes, path);
            ruleForm.ShowDialog();
            List<string> resultList = ruleForm.CodeList;

            if (ruleForm.DialogResult == System.Windows.Forms.DialogResult.OK)
            {
                int count = 0;
                int total = 0;
                for (int i = 0; i < elementsList.Keys.Count; i++)
                {
                    string codeName = elementsList.Keys.ElementAt(i);
                    total += elementsList[codeName].Count;
                }

                ProgressBarExport progressBar = new ProgressBarExport();
                progressBar.Text = "清单编码";
                progressBar.progressBarEx.Minimum = 0;
                progressBar.SetTextInfo("清单编码(" + count.ToString() + "/" + total.ToString() + ")", 0L);
                progressBar.Show();
                progressBar.progressBarEx.Maximum = total;

                for (int i = 0; i < elementsList.Keys.Count; i++)
                {
                    Dictionary<string, List<string>> codeTextNums = new Dictionary<string, List<string>>();
                    string codeName = elementsList.Keys.ElementAt(i);
                    string keyWords = "";

                    for (int j = 0; j < resultList.Count; j++)
                    {
                        if (resultList[j].Contains(codeName))
                        {
                            keyWords = resultList[j].Split('-')[1];
                            break;
                        }
                    }


                    for (int j = 0; j < elementsList[codeName].Count; j++)
                    {
                        string numText = "";
                        ElementId id = new ElementId(int.Parse(elementsList[codeName][j].Remove(0, 2)));
                        Element element = doc.GetElement(id);
                        var texts = keyWords.Split(',');
                        foreach (string text in texts)
                        {
                            numText += GetCountText(element, text) + "$";
                        }
                        string codeText = (codeName + "$" + numText).TrimEnd('$');

                        if (codeTextNums.ContainsKey(codeText))
                        {
                            codeTextNums[codeText].Add(elementsList[codeName][j]);
                        }
                        else
                        {
                            codeTextNums.Add(codeText, new List<string>());
                            codeTextNums[codeText].Add(elementsList[codeName][j]);
                        }
                    }

                    int codeIndex = 1;
                    var keys = codeTextNums.Keys.ToList();
                    keys.Sort();

                    for (int j = 0; j < keys.Count; j++)
                    {
                        for (int k = 0; k < codeTextNums[keys[j]].Count; k++)
                        {
                            XmlNode idNode = mainNode.SelectSingleNode(codeTextNums[keys[j]][k]).SelectSingleNode("项目编码");
                            XmlNode textNode = mainNode.SelectSingleNode(codeTextNums[keys[j]][k]).SelectSingleNode("项目特征");
                            if (keys[j].Split('$').Count() > 1)
                            {
                                idNode.InnerText = keys[j].Split(' ')[0] + codeIndex.ToString("000");
                                textNode.InnerText = keys[j].Split('$')[1];
                            }
                            else
                            {
                                idNode.InnerText = "";
                                textNode.InnerText = "";
                            }

                            count++;
                            progressBar.PerformStep();
                            progressBar.SetTextInfo("清单编码(" + count.ToString() + "/" + total.ToString() + ")", 0L);
                            if (progressBar.progressBarEx.Value == total)
                            {
                                progressBar.Dispose();
                            }
                            if (progressBar.bAbort)
                            {
                                progressBar.Dispose();
                                progressBar.Close();
                                return Result.Cancelled;
                            }
                        }
                        codeIndex++;
                    }
                }
                xml.Save(path);
                TaskDialog.Show("Revit", "清单编码成功！！");

            }

            return Result.Succeeded;
        }

        private string GetCountText(Element element, string text)
        {
            switch (text)
            {
                case "混凝土强度等级":
                    return GetMaterial(element);

                default:
                    return "";
            }
        }

        private string GetMaterial(Element element)
        {
            Document doc = element.Document;
            switch (element.Category.Name)
            {
                case "墙":
                    Wall wall = element as Wall;
                    WallType wallType = wall.WallType;
                    CompoundStructure structure = wallType.GetCompoundStructure();
                    IList<CompoundStructureLayer> layers = structure.GetLayers();
                    foreach (CompoundStructureLayer layer in layers)
                    {
                        if (layer.Function == MaterialFunctionAssignment.Structure)
                        {
                            return (doc.GetElement(layer.MaterialId) as Material).Name;
                        }
                    }
                    return "";
                case "楼板":
                    Floor floor = element as Floor;
                    FloorType floorType = floor.FloorType;
                    CompoundStructure structureFloor = floorType.GetCompoundStructure();
                    IList<CompoundStructureLayer> layersFloor = structureFloor.GetLayers();
                    foreach (CompoundStructureLayer layer in layersFloor)
                    {
                        if (layer.Function == MaterialFunctionAssignment.Structure)
                        {
                            return (doc.GetElement(layer.MaterialId) as Material).Name;
                        }
                    }
                    return "";
                case "结构框架":
                case "结构柱":
                    ElementId materialId = element.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM).AsElementId();
                    return (doc.GetElement(materialId) as Material).Name;
                default:
                    return "";
            }
        }
    }
}
